// 直接使用字面量进行类型声明
let a: 10
a = 10
// a = 11//报错a只能赋值字面量10
// b = 'wzc3'//报错必须在竖线的范围内，|是或的意思 
let b : 'wzc1' | 'wzc2';
b = 'wzc1'
b = 'wzc2'
// c是联合类型既可以是布尔值也可以是字符串
let c : boolean | string
//any 是所有类型，用any定义的变量可以使用所有的类型，对一个变量设置为any后，相当于ts对改变量关闭了ts检测，不建议使用
//声明变量如果不指定类型，ts解析器会自动判断变量为any，成为隐式any，这种情况我们要避免
let d : any
d = true
d = 'sad'
// unkown表示未知类型的值，是一个类型安全的any
let e : unknown
e = 10
e = true
e = 'sda'
// unkown和any的区别
let s : string
// s = d //这样的话不会报错，但是s也不再是string类型，也会变成any类型，关闭ts检测
// s = e //这样的话会报错，报错信息为不能将unkown类型的值赋值给string类型 
// unkown不能直接赋值给其他类型变量，如果要赋值可以使用
if(typeof e === 'string'){
    s = e
}
// 还可以使用ts的类型断言,断言的作用就是告诉编译器他就是某种类型
/*
    语法：
        变量 as 类型
        <类型>变量
*/
s = e as string
s = <string>e
// void用来表示空，以函数为例就表示没有返回值的函数
function  fn() : void {
    // return 'dwa'//报错，返回值应该为空，要么没有return有的话不可以有返回值
    return
}
// never表示永远没有返回结果
function  fn2():never {
    throw new Error('报错')
}
// object对象类型,object范围太广了，一般开发中不会使用
let o :object
o = {}
o = function () {}
// 可以在花括号里面写一些限制,指定对象包含哪些属性
/*
    语法：{属性名:属性值,属性名:属性值,属性名?:属性值}//在属性名后面加上括号代表可选属性
*/
let n : {name: string}
// n = {}//报错需要有name属性才可以
n = {name:'wzc'}
// [propName:string]:any表示任意属性
let m : {name:string,[propName:string]:any}
m = {name:'wzc',age:12,gender:'男'}
// 对函数参数和返回值进行类型限制限制
/*
    语法:(形参:类型,形参:类型...)=>返回值
*/
let q : (a:number,b:number)=>number
q = function (n1:number,n2:number):number {
    return n1+n2
}
// 语法：方式一:类型[] 方式二:array<类型>
// string[]表示字符串类型数组
let v : string[]
v = ['a','b','c']
// number[]表示数值类型数组
let y : number[]
let g : Array<any>
/*
    元组，元组是固定长度的数组，当数组中数量的值是固定的元组效率高
*/ 
let h : [string,string]
h = ['da','dasda']//长度要和定义的数量一样
/*
    enum枚举
        枚举有点像java，你可以定义一个枚举，类似于类的概念
*/
enum Gender{
    male ,
    famale 
}
let i : {name:string,gender:Gender}
i = {
    name: 'wzc',
    gender : Gender.male
}
// |表示或&表示与
let j : {name:string}&{age:number}
let p : {name:string}|{age:number}
// 类型的别名
type myType = 1 | 2 | 3 | 4
let ag1 : 1 | 2 | 3 | 4
let ag2 : 1 | 2 | 3 | 4
let ag3 : myType